#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cv.h>
#include <highgui.h>
#include <assert.h>
#include "sr.h"
#include "foo.h"
using namespace std;
using namespace cv;

void pre();
void correct_1(unsigned char *data, int step, int x, int y, int val, int c);
void correct_2(unsigned char *data, int step, int x, int y, int val, int c);
int gaosi(const unsigned char *data, int step, int x, int y, int c);
void pocs(char *);
void ruihua(IplImage *);
void ruihua_cv(IplImage *src);
void ruihuaMat(char *);

static IplImage *cankao;
static IplImage *tmpImage;
static IplImage *hrImage;
static IplImage *lrImage;
static int width;
static int height;
static unsigned char *data_tmp;
static unsigned char *data_hr;
static unsigned char *data_lr;
static unsigned char *data_cankao;
static int step_tmp;
static int step_hr;
static int step_lr;
static int step_cankao;
const int U1 = 8;
const int U2 = 30;

int main()
{
	pre();
	pocs((char*)"res/result/0.png");
	pocs((char*)"res/result/1.png");
	pocs((char*)"res/result/2.png");
	pocs((char*)"res/result/3.png");
	pocs((char*)"res/result/4.png");
	pocs((char*)"res/result/5.png");
	pocs((char*)"res/result/6.png");
	pocs((char*)"res/result/7.png");
	pocs((char*)"res/result/8.png");
	pocs((char*)"res/result/9.png");
	pocs((char*)"res/result/10.png");
	pocs((char*)"res/result/11.png");
	pocs((char*)"res/result/12.png");
	pocs((char*)"res/result/13.png");
	IplImage *cankao_ = cvCreateImage(
			cvSize(width * 3, height * 3),
			IPL_DEPTH_8U,
			1
			);
	cvCvtColor(cankao, cankao_, CV_BGR2GRAY);
	canny(cankao_, cankao_, 35, 70, 3);
	return 0;
}

void pre()
{
	tmpImage = cvLoadImage("res/result/1.png");
	assert(tmpImage);
	width = tmpImage->width;
	height = tmpImage->height;
	assert(width);
	assert(height);
	cankao = cvCreateImage(
			cvSize(width * 3, height * 3),
			IPL_DEPTH_8U,
			3
			);
	cvResize(tmpImage, cankao, CV_INTER_CUBIC);
#ifdef DEBUG
	cvNamedWindow("cankao");
	cvShowImage("cankao", cankao);
	ruihua_cv(cankao);
	cvWaitKey(0);
#endif

	return;
}

void pocs(char *fileName)
{
	tmpImage = cvLoadImage(fileName);
	ruihua_cv(tmpImage);
	assert(tmpImage);
	width = tmpImage->width;
	height = tmpImage->height;
	step_tmp = tmpImage->widthStep;
	step_cankao = cankao->widthStep;
	data_tmp = (unsigned char *) tmpImage->imageData;
	data_cankao = (unsigned char *) cankao->imageData;
	int R = 0;
	int x;
	int y;
	int channel = cankao->nChannels;
	for (int i = 1; i < height - 1; ++ i) {
		for (int j = 1; j < width - 1; ++ j) {
			for (int c = 0; c < 3; ++ c) {
				x = i * 3;
				y = j * 3;
				//R = (int)data_tmp[i * step_tmp + j * 3 + c] - gaosi(data_cankao, step_cankao, x, y, c);
				R = (int)data_tmp[i * step_tmp + j * 3 + c] - data_cankao[x * step_cankao + y * 3 + c];
				printf("the R is : %d\n", R);
				if (R < (-U1) && R > (-U2)) {
					correct_1(data_cankao, step_cankao, x, y, R + U1, c);
				}
				else if (R <= U1 && R >= (-U1)) {
				}
				else if (R > U1 && R < U2){
					correct_1(data_cankao, step_cankao, x, y, R - U1, c);
				}
				else {
					correct_2(data_cankao, step_cankao, x, y, 3, c);
				}
			}
		}
	}
#ifdef DEBUG
	cvNamedWindow("result");
	cvShowImage("result", cankao);
	cvWaitKey(0);
#endif
}

int xx[] = {
	-1,-1,-1,
	0, 0, 0,
	1, 1, 1
};
int yy[] = {
	-1,0,1,
	-1,0,1,
	-1,0,1
};
int w[] = {
		1, 2, 1,
		2, 4, 2,
		1, 2, 1
	};

int gaosi(const unsigned char *data, int step, int x, int y, int c)
{
	int _x;
	int _y;
	int result = 0;
	for (int i = 0; i < 9; ++ i) {
		_x = x + xx[i];
		_y = y + yy[i];
		result += (int)data[_x * step + _y * 3 + c] * w[i];
	}

	return result / 16;
}

void correct_1(unsigned char *data, int step, int x, int y, int val, int c)
{
	int _x;
	int _y;
	int tmp;
	for (int c = 0; c < 3; ++ c) {
		for (int i = 0; i < 9; ++ i) {
			_x = x + xx[i];
			_y = y + yy[i];
			tmp = (int)data[_x * step + _y * 3 + c] + val * w[i] / 16;
			if (tmp < 0) {
				tmp = 0;
			}
			if (tmp > 255) {
				tmp = 255;
			}
			data[_x * step + _y * 3 + c] = tmp;
		}
	}

	return;
}
void correct_2(unsigned char *data, int step, int x, int y, int val, int c)
{
	int _x;
	int _y;
	int tmp;
	for (int c = 0; c < 3; ++ c) {
		for (int i = 0; i < 9; ++ i) {
			_x = x + xx[i];
			_y = y + yy[i];
			tmp = (int)data[_x * step + _y * 3 + c] + val;
			if (tmp < 0) {
				tmp = 0;
			}
			if (tmp > 255) {
				tmp = 255;
			}
			data[_x * step + _y * 3 + c] = tmp;
		}
	}

	return;
}

void ruihua(IplImage *src)
{
	/*
	*/
	int xx[] = {
		-1,-1,-1,
		0,0,0,
		1,1,1
	};
	int yy[] = {
		-1,0,1,
		-1,0,1,
		-1,0,1
	};
	int w[] = {
		-1,-1,-1,
		-1,9,-1,
		-1,-1,-1
	};
	int _x;
	int _y;
	int height = src->height;
	int width  = src->width;
	int step = src->widthStep;
	int c = src->nChannels;
	unsigned char *data = (unsigned char *) src->imageData;
	unsigned char *tmp = (unsigned char *) malloc (sizeof(char) * step * height);
	memset(tmp, 0, sizeof(char) * step * height);
	int t = 0;
	for (int i = 1; i < height - 1; ++ i){
		for (int j = 1; j < width - 1; ++ j) {
			for (int k = 0; k < c; ++ k) {
				t = 0;
				for (int x = 0; x < 9; ++ x) {
					_x = i + xx[x];
					_y = j + yy[x];
					t += (int)data[_x * step + _y * c + k] * w[x];
				}
				tmp[i * step + j * c + k] = (unsigned char)t;
			}
		}
	}
	for (int i = 1; i < height - 1; ++ i){
		for (int j = 1; j < width - 1; ++ j) {
			for (int k = 0; k < c; ++ k) {
				data[i * step + j * c + k] = tmp[i * step + j * c + k];
			}
		}
	}
#ifdef DEBUG
	cvNamedWindow("ruihua");
	cvShowImage("ruihua", src);
	cvWaitKey(0);
#endif

	return;
}

void ruihuaMat(char *fileName)
{
	Mat src = imread(fileName);
	Mat dst;
	Mat kernel = (Mat_<float>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
	cv::filter2D(src, dst, src.depth(), kernel);
	imshow("src", src);
	imshow("dst", dst);
	cvWaitKey(0);
	return;
}

void ruihua_cv(IplImage *src)
{
	Mat mat = cvarrToMat(src);
	Mat kernel = (Mat_<int>(3, 3) << -1, -1, -1, -1, 9, -1, -1, -1, -1);
	Mat t;
	cv::filter2D(mat, t, mat.depth(), kernel);
	IplImage s = IplImage(t);
	cvCopy(src, &s);
}
